﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Reflection;
using System.Drawing.Drawing2D;
using System.IO;
using System.Text.RegularExpressions;


namespace eBirdAttend
{ 

    public partial class DeviceConfigure : UserControl
    {
        //BMJO sreedanya memeber varaibles must start with underscore. You are not following
        //coding standards. Next time i dont want to see varaible name like this. You must correct 
        //it in these code
       
        UserControl _UserControls;
        //BMJO these two are actually temp varaibles no need to make it as a mmber varaibel
        //PictureBox pctBox;
        //CheckBox chkBox;

        #region memberVariables
        string _imageUrl;
        string _deviceName;
        static int _imagePointX;
        static int _imagePointY;
        static int _chkPointX;
        static int _chkPointY;
        static string _maxWidth;
        string _Id="";
        int _count = 0;
        #endregion memberVariables

        List<DeviceInfo> _deviceInfoList = new List<DeviceInfo>();
        
        public DeviceConfigure()
        {
            InitializeComponent();
        }

        #region Properties
        public static string _deviceConfig;

        public string DeviceConfig
        {
            get { return _deviceConfig; }
            set { _deviceConfig = value; }
        }
        #endregion Properties

        private void DeviceConfigure_Load(object sender, EventArgs e)
        {
            _maxWidth = groupBox1.Width.ToString() ;
            //BMJO
            //Danya: You have to fill the device list with already configured devices.
            //But do that with collection I created. 
            //when ever you are adding or removing device it must be from the collection 
            //only _deviceInfoList.
            //This collection is then added to list control.
            //When user press save button save it to Installed devices.
            //While saving to installed device make sure you are not creating
            //duplicate entries. Easiest method is to delete all installed
            //device nodes from XML (DOM) and then save it a fresh from the
            //_deviceInfoList 

            DeviceInfoLoad();   //to display all supported devices
            FindInstalledDev();  //to search installed devices            
        }
        
        public void DeviceInfoLoad()
        {           
            XmlDocument settingsFile = new XmlDocument();
            settingsFile.Load("config.xml");
            XmlNode rootNode = settingsFile.DocumentElement;
            XmlNodeList DevList = rootNode.SelectNodes("/eOffice/SupportedDev/device");
            PictureBox pctBox;
            CheckBox chkBox;
            _imagePointX = 45;
            _imagePointY = 26;
            for (int i = 0; i < DevList.Count; ++i)
            {            
                
                if (DevList[i].Attributes["Name"] == null) continue;
                    DeviceInfo devInfo = new DeviceInfo();               

                    _deviceName = DevList[i].Attributes["Name"].Value;
                    devInfo.DeviceName = _deviceName;
                    XmlNode imageList = DevList[i].SelectSingleNode("descendant::Image");
                    _imageUrl = imageList.InnerText;
                    if (Convert.ToDouble(_imagePointX) > Convert.ToDouble(_maxWidth))
                    {
                        _imagePointX = 45;
                        _imagePointY = 156;
                    }
                    pctBox = new PictureBox();
                    pctBox.Image = Image.FromFile(_imageUrl);
                    pctBox.Location = new Point(_imagePointX, _imagePointY);
                    pctBox.Size = new Size(108, 97);
                    pctBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
                    pctBox.BorderStyle = BorderStyle.Fixed3D;
                    pctBox.BackColor = Color.Tan;
                    groupBox1.Controls.Add(pctBox);
                    _chkPointX =_imagePointX+ 7;
                    _chkPointY =_imagePointY+ 103;
                    chkBox = new CheckBox();                    
                    chkBox.Location = new Point(_chkPointX, _chkPointY);
                    chkBox.Size = new Size(88, 19);
                    chkBox.Name = "CheckBox" + i;
                    chkBox.Text = _deviceName;
                    groupBox1.Controls.Add(chkBox);
                    _imagePointX += 140;
                    _imagePointY += 0;

                    XmlNode driverPath = DevList[i].SelectSingleNode("descendant::DriverPath");
                    devInfo.DeviceDllPath = driverPath.InnerText;

                    devInfo.DevicePicture = pctBox;
                    devInfo.SelectionChkBox = chkBox;
                    //Here i am adding the device info class to list control for future use.
                  
                    _deviceInfoList.Add(devInfo);
                
            }
        }        

        public void FindInstalledDev()
        {
           
            listBox1.Items.Clear();
            XmlDocument doc = new XmlDocument();
            doc.Load("Config.xml");

            XmlNodeList nodes = doc.SelectNodes("/eOffice/InstalledDevices/device");

            foreach (XmlNode node in nodes)
            {
                foreach (Control control in this.groupBox1.Controls)
                {
                    if (control is CheckBox)
                    {
                        if (node.Attributes["Name"].Value.Contains(control.Text))
                        {
                            DeviceInfo devInfo = new DeviceInfo();
                            devInfo.DeviceName = node.Attributes["Name"].Value.ToString();
                            //listBox1.Items.Add(devInfo.DeviceName.ToString());
                            ((CheckBox)control).Checked = true;
                            //listBox1.Items.Clear();
                            foreach (DeviceInfo devInfos in _deviceInfoList)
                            {
                                if (devInfos.IsSelected())
                                {
                                    foreach (object objList in listBox1.Items)
                                    {
                                        if (objList == devInfo)
                                            goto ExistingItem;
                                    }
                                    devInfo.DeviceDllPath = devInfos.DeviceDllPath;
                                    listBox1.Items.Add(devInfo);
                                    AddToInstalledDev(devInfo);
                                    //((CheckBox)control).Checked = false;
                                }
                            }
                        }

                    }
                }
            ExistingItem:
                { }
            }
      
            //XmlNodeList nodes = doc.SelectNodes("/eOffice/InstalledDevices/device");

            //foreach (XmlNode node in nodes)
            //{
            //    DeviceInfo devinfo3 = new DeviceInfo();
            //    devinfo3.DeviceName = node.Attributes["Name"].Value.ToString();
            //    listBox1.Items.Add(devinfo3);
            //    AddToInstalledDev(devinfo3);
            //}      

           
        }


        private void btnAdd_Click(object sender, EventArgs e)
        {
            //listBox1.Items.Clear();
       //BMJO
       //Danya please see that I am adding the deviceinfo object as it is to the 
       //list. This will avoid serch in the list when a selectec item is returned.
       //To add objects like this your object must support ToString function to return the
       //value that to be displayed in the list box.
            foreach (DeviceInfo devInfo in _deviceInfoList)
            {
                if (devInfo.IsSelected())
                {

                    for (int i = 0; i < listBox1.Items.Count; i++)
                    {
                        if (listBox1.Items[i].ToString() == devInfo.DeviceName)
                        {
                            _count++;
                            devInfo.DeviceName = devInfo + "_out";

                        }
                    }
                    listBox1.Items.Add(devInfo);                    
                    AddToInstalledDev(devInfo);
                    devInfo.SelectionChkBox.CheckState=CheckState.Unchecked;
                }
            }
       }

        private void AddToInstalledDev(DeviceInfo devInfoInst)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("Config.xml");
            XmlNodeList  _existNode = doc.SelectNodes("/eOffice/InstalledDevices/device");
            foreach (XmlNode _xmlExistNode in _existNode)
            {
                if (_xmlExistNode.Attributes["Name"].Value.ToString() == devInfoInst.ToString())
                    return;
                _Id = (Int32.Parse(_xmlExistNode.Attributes["ID"].Value) + 1).ToString();
            }
            
            if (_Id == "")
                _Id = "1";

            //Create New Element in xml..
            XmlElement newXmlElement = doc.CreateElement("device");

            newXmlElement.SetAttribute("ID", _Id);
            newXmlElement.SetAttribute("Name", devInfoInst.ToString());
            newXmlElement.SetAttribute("Enabled", "yes");

            string xmlQuery = "/eOffice/InstalledDevices/device[@ID = '" + (Int32.Parse(_Id) - 1).ToString() + "']";

            //Find the specific node
            XmlNode _xmlNode = doc.SelectSingleNode(xmlQuery);

            if (_xmlNode != null)
            {
                //Find the common parent of the MainCategory node
                XmlNode commonParent = _xmlNode.ParentNode;
                commonParent.InsertAfter(newXmlElement, _xmlNode);
            }
            //Insert the node
            else
            {
                XmlNodeList _firstNode = doc.SelectNodes("/eOffice/InstalledDevices");
                _firstNode[0].AppendChild(newXmlElement);

                // doc.DocumentElement.LastChild.AppendChild(newXmlElement);
            }
           
            doc.Save("config.xml");
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            try
            {
                foreach (int i in listBox1.SelectedIndices)
                {
                    object itemToRemove = listBox1.Items[i];
                    listBox1.Items.Remove(itemToRemove);
                    RemoveFrmInstalledDev(Convert.ToString(itemToRemove.ToString()));
                    DeviceInfo _devInfo = new DeviceInfo();
                    _devInfo.DeviceName = Convert.ToString(itemToRemove.ToString());
                    _deviceInfoList.Remove(_devInfo);
                    _deviceInfoList.RemoveAt(Convert.ToInt32(listBox1.SelectedIndex) + 1);
                    
                }
            }
            catch (Exception ex)
            {
            }
        }

        private void RemoveFrmInstalledDev(string RemovingItem)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("Config.xml");
            XmlNodeList _NodeList = doc.SelectNodes("/eOffice/InstalledDevices/device");
            foreach (XmlNode _xmlNode in _NodeList)
            {
                if (_xmlNode.Attributes["Name"].Value.ToString() == RemovingItem)
                    _xmlNode.ParentNode.RemoveChild(_xmlNode);
            }
            doc.Save("config.xml");
        }

        public string GetId(DeviceInfo devInfo)
        {
            string _dev="";
            XmlDocument doc = new XmlDocument();
            doc.Load("Config.xml");
            XmlNodeList _NodeList = doc.SelectNodes("/eOffice/InstalledDevices/device");
            foreach (XmlNode _xmlNode in _NodeList)
            {
                if (_xmlNode.Attributes["Name"].Value.ToString() == devInfo.ToString())
                    _dev= _xmlNode.Attributes["ID"].Value.ToString();
            }
            return _dev;
        }

        private void LoadDeviceConfigControl(DeviceInfo devInfo)
        {
            try
            {
                string _devId = GetId(devInfo);
                //MessageBox.Show(devInfo.DeviceDllPath);
                UserControl _ucDynamicalyLoaded;
                if ((devInfo.DeviceDllPath == null) || (devInfo.DeviceDllPath == ""))
                {
                    MessageBox.Show("Device Dll path not specified in the configuration file");
                    return;
                }
                Assembly assembly = Assembly.LoadFrom(devInfo.DeviceDllPath);

                foreach (Type type in assembly.GetTypes())
                {
                    if (type.IsClass == true)
                    {
                        //MessageBox.Show(type.FullName.ToString());
                        //BMJO
                        //Danya, All our device dll must contain a user control named exctly same as
                        //given below. Or this can be a XML setting. If it is an XML settings then user can
                        //name it as they like. But then you have to read it and use it here insted of the
                        //hardcoded control name. Letus go like this for the time being
                        if (type.FullName.EndsWith("." + "DeviceConfigureUserControl"))
                        {

                            //If you have more than one user control in one dll use
                            //specific name here.
                            _ucDynamicalyLoaded = (UserControl)Activator.CreateInstance(type);
                            _ucDynamicalyLoaded.Location = new System.Drawing.Point(10, 20);
                            _ucDynamicalyLoaded.Name = "deviceconfigure";
                            _ucDynamicalyLoaded.Size = new System.Drawing.Size(560, 500);
                            _ucDynamicalyLoaded.TabIndex = 1;
                            // create an instance of the class
                            object classObject = Activator.CreateInstance(type);
                            type.GetProperty("Id").SetValue(classObject, _devId, null);
                            groupBox1.Controls.Add(_ucDynamicalyLoaded);
                            _ucDynamicalyLoaded.Visible = true;
                            _ucDynamicalyLoaded.BringToFront();
                            this.Text = "eoffice --- device configure";


                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }

        }

        private void btnConfigure_Click(object sender, EventArgs e)
        {
     
            //if(listBox1.SelectedItem.ToString() == "")
            if (listBox1.SelectedItems.Count == 0)
            {
                MessageBox.Show("Please select a device");
                return;
            }
            else if (listBox1.SelectedItems.Count > 1)
            {
                MessageBox.Show("Please select one device only");
                return;
            }

            DeviceInfo devInfo = (DeviceInfo)listBox1.SelectedItem;
            
            LoadDeviceConfigControl(devInfo);
       
        }

               
    }

    /// <summary>
    /// This class is used to hold the device informations.This will avoid checking xml
    /// file evry time for details.
    /// </summary>
    public class DeviceInfo:Object
    {
        PictureBox _pbPictBox;
        CheckBox _chkSelectDevice;
        string _deviceName;
      
        string _deviceDllPath;
        
        public string DeviceDllPath
        {
            set { _deviceDllPath = value; }
            get { return _deviceDllPath; }

        }
        public string DeviceName
        {
            set
            {
                _deviceName = value;
            }
            get
            {
                return _deviceName;

            }
        }
        public PictureBox DevicePicture
        {
            get { return _pbPictBox; }
            set { _pbPictBox = value; }
        }

        public CheckBox SelectionChkBox
        {
            get { return _chkSelectDevice; }
            set { _chkSelectDevice = value; }
        }

        public bool IsSelected()
        {
            return _chkSelectDevice.Checked;
        }
        public override string ToString()
        {           
            return _deviceName;
        }
      
    }
}
